package com.shift.sdk;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.WindowManager.LayoutParams;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;

import com.shift.ccsdk.CCBasePoint;
import com.shift.ccsdk.CCDetail;
import com.shift.ccsdk.CCSDK;
import com.shift.sdk.dialog.OptionDialog;
import com.shift.sdk.dialog.SelectDialog;
import com.shift.sdk.R;

/**
 * Pictureモードのアクティビティクラス.
 *
 * @author SHIFT
 */
public class PictureActivity extends Activity implements OnItemClickListener {

    /**
     * ダイアログ用定数(解析).
     */
    private static final int DIALOG_ANALYZE_PICTURE = 0;

    /**
     * ダイアログ用定数(設定).
     */
    private static final int DIALOG_OPTION = 1;

    /**
     * 解析オプション.
     */
    public static AnalyzeOption option = new AnalyzeOption();

    /**
     * 解析対象画像を表示するビュー.
     */
    private ImageView analyzeView;

    /**
     * 初期ビュー.
     */
    private TextView text;

    /**
     * カメラ撮影時のプレビュー.
     */
    private PicturePreview picturePreview;

    /**
     * 解析ボタン.
     */
    private Button analyzeButton;

    /**
     * 解析結果リスト.
     */
    private List<CCDetail> analyzeResultList;

    /**
     * 基準点リスト.
     */
    private List<CCBasePoint> basePointList;

    /**
     * 解析結果リストアダプタ.
     */
    private CCIdListAdapter adapter;

    /**
     * ギャラリーまたはカメラ撮影したオリジナルのイメージ.
     */
    private Bitmap originalBitmap;

    /**
     * ギャラリーまたはカメラ撮影したオリジナルのイメージを設定する.
     *
     * @param originalBitmap
     *            ギャラリーまたはカメラ撮影したオリジナルのイメージ
     */
    public void setOriginalBitmap(Bitmap originalBitmap) {
        this.originalBitmap = originalBitmap;
    }

    /**
     * アクティビティ起動時の処理.
     */
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.picture);

        text = (TextView) findViewById(R.id.image_empty);
        text.setOnTouchListener(new OnTouchListenerForPicture());

        // ディスプレイサイズ
        DisplayMetrics metrics = getResources().getDisplayMetrics();

        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
                LayoutParams.WRAP_CONTENT);
        params.height = (int) (metrics.heightPixels * 0.4);
        params.width = (int) (metrics.widthPixels);
        text.setLayoutParams(params);
        picturePreview = (PicturePreview) findViewById(R.id.image_camera);
        picturePreview.setOnTouchListener(new TakePictureListener());
        picturePreview.setLayoutParams(params);

        analyzeView = (ImageView) findViewById(R.id.image_select);
        analyzeView.setLayoutParams(params);

        analyzeButton = (Button) findViewById(R.id.button_analyze);
        analyzeButton.setOnClickListener(new AnalyzeListener());

        // リスト生成
        List<CCInfo> list = new ArrayList<CCInfo>();
        adapter = new CCIdListAdapter(getApplicationContext(), R.layout.list_low, list);
        ListView ccIdList = (ListView) findViewById(R.id.ccIdList);
        ccIdList.setAdapter(adapter);
        ccIdList.setItemsCanFocus(false);
        ccIdList.setOnItemClickListener(this);
        adapter.notifyDataSetChanged();
    }

    /**
     * カメラ撮影時のリスナー.
     *
     * @author SHIFT
     */
    private class TakePictureListener implements OnTouchListener {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if (event.getAction() == MotionEvent.ACTION_UP) {
                picturePreview.takePicture();
            }
            return true;
        }
    }

    /**
     * 解析ボタン押下時のリスナー.
     *
     * @author SHIFT
     */
    private class AnalyzeListener implements android.view.View.OnClickListener {

        @Override
        public void onClick(View v) {

            // 画像が選択されている場合
            if (analyzeView.getVisibility() == View.VISIBLE) {

                analyzeView.setImageBitmap(originalBitmap);
                // 非同期で解析処理を行う
                new AnalyzeTask(PictureActivity.this).execute();
            }
        }
    }

    /**
     * ダイアログ生成.
     */
    @Override
    protected Dialog onCreateDialog(int id) {

        Dialog dialog = null;
        switch (id) {
        // 画像選択ダイアログの場合
        case DIALOG_ANALYZE_PICTURE:
            dialog = new SelectDialog(this).create();
            break;
        // 設定ダイアログの場合
        case DIALOG_OPTION:
            dialog = new OptionDialog(this).create();
            break;
        }
        dialog.setCanceledOnTouchOutside(false);
        return dialog;
    }

    /**
     * ギャラリーから画像を選択した際の処理.
     */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {

        if (resultCode == RESULT_OK) {

            try {
                InputStream in = getContentResolver().openInputStream(data.getData());
                Bitmap img = BitmapFactory.decodeStream(in);
                in.close();

                // 選択した画像を表示
                originalBitmap = img.copy(Config.ARGB_8888, true);
                analyzeView.setImageBitmap(img);

            } catch (Exception e) {
                e.printStackTrace();
            }
            analyzeView.setVisibility(View.VISIBLE);
            analyzeButton.setVisibility(View.VISIBLE);
            text.setVisibility(View.GONE);
        }
    }

    /**
     * オプションメニューの設定
     */
    public boolean onPrepareOptionsMenu(Menu menu) {
        boolean ret = super.onPrepareOptionsMenu(menu);
        menu.clear();
        menu.add(0, Menu.FIRST, Menu.NONE, "設定").setIcon(android.R.drawable.ic_menu_preferences);
        return ret;
    }

    /**
     * オプションメニュー押下時の処理
     */
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        showDialog(DIALOG_OPTION);
        return super.onOptionsItemSelected(item);
    }

    /**
     * 選択したカメレオンコードの枠線描画.
     */
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {

        boolean isChecked = adapter.getItem(position).isChecked();
        adapter.getItem(position).setChecked(!isChecked);
        adapter.notifyDataSetChanged();

        // チェックされているCCIDを抽出
        List<CCDetail> targetAnalyzeResultList = new ArrayList<CCDetail>();
        List<CCBasePoint> targetBasePointList = new ArrayList<CCBasePoint>();
        for (int i = 0; i < analyzeResultList.size(); i++) {

            if (adapter.getItem(i).isChecked()) {
                targetAnalyzeResultList.add(analyzeResultList.get(i));
                targetBasePointList.add(basePointList.get(i));
            }
        }

        Bitmap convertedBitmap = null;
        // 基準点描画オプションが設定されている場合
        if (PictureActivity.option.isDrawBasePoint()) {
            // カメレオンコードの枠線と基準点を描画
            convertedBitmap = CCSDK.DrawCodeAreaPoint(originalBitmap,
                    targetAnalyzeResultList,
                    targetBasePointList,
                    option.getThickness());
        } else {
            // カメレオンコードの枠線を描画
            convertedBitmap = CCSDK.DrawCodeArea(originalBitmap,
                    targetAnalyzeResultList,
                    option.getThickness());
        }

        // 枠線描画
        analyzeView.setImageBitmap(convertedBitmap);
    }

    /**
     * 画像選択ビュータッチ時のリスナー.
     *
     * @author SHIFT
     */
    private class OnTouchListenerForPicture implements View.OnTouchListener {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            showDialog(DIALOG_ANALYZE_PICTURE);
            return true;
        }
    }

    /**
     * 解析処理用の非同期タスク.
     *
     * @author SHIFT
     */
    private class AnalyzeTask extends AsyncTask<Void, Void, Void> {

        /**
         * プログレスダイアログ.
         */
        private ProgressDialog dialog;

        /**
         * アクティビティ.
         */
        private Activity activity;

        /**
         * コンストラクタ.
         *
         * @param activity
         *            アクティビティ
         */
        public AnalyzeTask(Activity activity) {
            this.activity = activity;
        }

        /**
         * バックグラウンドの処理.
         */
        @Override
        protected Void doInBackground(Void... params) {

            // 解析
            analyzeResultList = CCSDK.Analyze(originalBitmap,
                    PictureActivity.option.getMaxCodeCount(),
                    PictureActivity.option.getAnalizeLevel());

            // 基準点取得
            basePointList = CCSDK.getCCPointBase();

            return null;
        }

        /**
         * 前処理.
         */
        @Override
        protected void onPreExecute() {
            super.onPreExecute();

            // プログレスダイアログを表示
            dialog = new ProgressDialog(activity);
            dialog.setTitle("解析中");
            dialog.setMessage("しばらくお待ちください.");
            dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
            dialog.show();
        }

        /**
         * 後処理.
         */
        @Override
        protected void onPostExecute(Void result) {
            super.onPostExecute(result);

            // 解析結果リストを再作成
            adapter.clear();
            for (int i = 0; i < analyzeResultList.size(); i++) {

                CCInfo info = new CCInfo();
                info.setNumber(String.valueOf(i + 1));
                info.setCcId(String.valueOf(analyzeResultList.get(i).ccId));
                info.setChecked(false);
                adapter.add(info);
            }
            dialog.dismiss();
        }
    }
}
